#include "InputSource.h"

#include <utility>
#include "Util/logc.h"
namespace Media{

InputSource::InputSource(SourceInterfaceEnum iEnum, SourceMediaType mType,
    std::string content, bool isCustom):Source(iEnum, mType, INPUT, std::move(content), isCustom){
    tracef("create InputSource");
    m_vmanager = VDecoderManager::Instance();
    m_amanager = ADecoderManager::Instance();

    if(iEnum != HDMI) {
        createDecoder();
    }
}

InputSource::~InputSource(){
    tracef("~InputSource");
}


bool InputSource::Start(){
    tracef(" InputSource Start ");
    if(isRunning()) return true;
    if(OpenSource()){
        setRunningState(true);
        return true;
    }
    
    return false;
}

bool InputSource::Stop(){
    tracef(" InputSource Stop ");
    if(!isRunning()) return false;
    CloseSource();
    destroyDecoder();
    setRunningState(false);
    return true;
}


bool InputSource::InputPacket(const FrameCommon::Frame::Ptr& frame){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(frame->isVideo() && m_vdecoder){
        m_vdecoder->InputFrame(frame);
    }else if(frame->isAudio() && m_adecoder){
        m_adecoder->InputFrame(frame);
    }
   
    return true;
}


InputSource::FrameConsumerId InputSource::AddAFrameConsumer(std::function<void (const AVFrame::Ptr)> framecb){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_adecoder){
        return m_adecoder->AddConsumer(std::move(framecb));
    }
    return 0;
}

bool InputSource::RemoveAFrameConsumer(FrameConsumerId id){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_adecoder){
        return m_adecoder->RemoveConsumer(id);
    }
    return false;
}


InputSource::FrameConsumerId InputSource::AddVFrameConsumer(std::function<void (const AVFrame::Ptr)> framecb){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_vdecoder){
        return m_vdecoder->AddConsumer(std::move(framecb));
    }
    return 0;
}


bool InputSource::RemoveVFrameConsumer(FrameConsumerId id){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_vdecoder){
        return m_vdecoder->RemoveConsumer(id);
    }
    
    return false;
}

bool InputSource::createDecoder(){
    tracef("createDecoder ");
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(!m_vdecoder && GetSourceMediaType() != AUDIO){
        if(!m_vmanager->CreateDecoder(m_vdecoder)) return false;
    }

    if(!m_adecoder && GetSourceMediaType() != VIDEO){
        if(!m_amanager->CreateDecoder(m_adecoder)) return false;
    }
    return true;
}


bool InputSource::destroyDecoder(){
    std::lock_guard<std::recursive_mutex> guard(m_mux);
    if(m_vdecoder){
        m_vmanager->ReleaseDecoder(m_vdecoder);
        m_vdecoder.reset();
    }
    if(m_adecoder){
        m_amanager->ReleaseDecoder(m_adecoder);
        m_adecoder.reset();
    }
    return true;
}


}